var fs = require('fs'),
    path = require('path');

var ROOT = path.resolve(__dirname, '../traces/self_defined_traces/');

var currentFlow,
    currentFlowSizeCDFRule,
    currentPacketSizeCDFRule,
    currentPacketIntervalCDFRule;

var protoMap = {
    'SMTP': 1,
    'HTTP': 1,
    'FTP': 0,
    'DNS': 0
};

function getRandom(cdf) {
    
    var random = Math.random(),
        value;

    for (var i = 0, len = cdf.length; i < len; i++) {
        if (random <= parseFloat(cdf[i].cdf)) {
            if (i == 0) {
                value = Math.random() * parseInt(cdf[i].value);
            } else {
                value = Math.random() * (parseInt(cdf[i].value) - parseInt(cdf[i-1].value));
            }
            value = Math.floor(value);
            break;
        }
    }

    return value;
}

function generateFlowByCDF(startTime, simuTime, fileName) {

    var random, flowSize, packetSize, 
        currentTime = startTime,
        stopTime = startTime,
        index = 0,
        packets = [];

    // generate flow size
    flowSize = getRandom(currentFlowSizeCDFRule);

    // generate packets of the flow
    while (currentTime <= simuTime) {
        packetSize = getRandom(currentPacketSizeCDFRule);
        if (packetSize > flowSize) break;
        flowSize -= packetSize;
        packets.push([index++, 'I', currentTime-startTime, packetSize].join(' '));
        stopTime = currentTime;
        currentTime += getRandom(currentPacketIntervalCDFRule);
    }

    // write packets to file
    fs.writeFileSync(fileName, packets.join('\n')); 

    return stopTime;
}

/**
 * Main Entry
 */

function generateFlowDescription(simuTime, flow, rule) { 

    // UNIT: us
    simuTime *= 1000000;
    currentFlow = flow;
    currentFlowSizeCDFRule = rule.flowSize;
    currentPacketSizeCDFRule = rule.packetSize;
    currentPacketIntervalCDFRule = rule.packetInterval;

    var fileName = [flow.src, flow.dst, flow.proto, flow.num].join('-'),
        content = '',
        server = [],
        startTime, stopTime, dstPort, tos, outFile;
    
    for (var i = 0, len = Number(flow.num); i < len; i++) {

        outFile = path.resolve(ROOT, fileName + '-' + i + '.txt');

        dstPort = Math.floor(Math.random() * 90 + 10);
        tos = Math.floor(Math.random() * 3);
        startTime = Math.floor(Math.random()*simuTime);
        stopTime = generateFlowByCDF(startTime, simuTime, outFile);

        server.push([flow.dst, dstPort, protoMap[flow.proto]].join('-'));
        content += [flow.src, flow.dst, dstPort, outFile, tos, startTime / 1000000, stopTime / 1000000, protoMap[flow.proto], '\n'].join(' '); 
    }

    console.log("[SIMULATION] content from self-defined cdf are\n", content);

    return {
        content: content,
        server: server
    };
}

// module exports
exports.generateFlowDescription = generateFlowDescription;
